import type { ViteDevServer } from 'vite'
import type {
  AutoRouterNode,
  AutoRouterOptions,
  NodeStatInfo,
  ParsedAutoRouterOptions,
  ResolvedGlob,
} from '../types'
import { generateDtsFile } from './dts'
import { generateSharedFile, generateTransformerFile } from './generate'
import { resolveGlobs } from './glob'
import { generateImportsFile } from './import'
import { getNodeStatInfo, resolveNodes } from './node'
import { resolveOptions } from './option'
import { generateRoutes } from './route'
import {
  initTemp,
  isInExcludeGlob,
  updateNodeBackup,
} from './temp'
import { FileWatcher } from './watcher'

export class AutoRouter {
  private options: ParsedAutoRouterOptions = {} as ParsedAutoRouterOptions
  globs: ResolvedGlob[] = []

  nodes: AutoRouterNode[] = []

  statInfo: NodeStatInfo = {
    add: [],
    rename: [],
  }

  watcher?: FileWatcher

  viteServer?: ViteDevServer

  constructor(options?: AutoRouterOptions, generate: boolean = false) {
    this.init(options, generate)
  }

  init(options?: AutoRouterOptions, generate: boolean = false): void {
    this.options = resolveOptions(options)
    if (generate) {
      this.generate()
    }
  }

  /**
   *  获取解析后的路由选项
   * @returns ParsedAutoRouterOptions
   */
  getOptions(): ParsedAutoRouterOptions {
    return this.options
  }

  async initGlobs(): Promise<void> {
    this.globs = await resolveGlobs(this.options)
  }

  async initNodes(): Promise<void> {
    this.nodes = resolveNodes(this.globs, this.options)
  }

  async initStatInfo(): Promise<void> {
    this.statInfo = await getNodeStatInfo(this.options.cwd, this.nodes)
  }

  /**
   * 生成路由
   * @returns void
   */
  async generate(): Promise<void> {
    await initTemp(this.options.cwd)
    await this.initGlobs()
    await this.initNodes()
    await this.initStatInfo()

    await generateDtsFile(this.nodes, this.options) // 生成 Generate Dts 文件
    await generateImportsFile(this.nodes, this.options) // 生成 Generate Imports 文件
    await generateTransformerFile(this.options) // 生成 Generate Transformer 文件
    await generateSharedFile(this.nodes, this.options) // 生成 Generate Shared 文件
    await generateRoutes(this.nodes, this.statInfo, this.options) // 生成 Generate Routes 文件
    await updateNodeBackup(this.options.cwd, this.nodes) //  更新节点备份
  }

  /**
   *
   */
  watch(): void {
    this.watcher = new FileWatcher(this.options)
    this.watcher?.start(async (glob) => {
      const isInExclude = await isInExcludeGlob(this.options.cwd, glob)

      if (isInExclude)
        return

      await this.generate()
    })
  }

  stopWatch(): void {
    this.watcher?.close()
  }

  setViteServer(server: ViteDevServer): void {
    this.viteServer = server

    this.viteServer.httpServer?.on('close', () => {
      this.stopWatch()
    })
  }

  reloadViteServer(): void {
    this.viteServer?.ws?.send({ type: 'full-reload', path: '*' })
  }
}
